package com.spider.service;

import com.spider.task.BaseTask;
import com.spider.task.PrintTimeTask;
import org.quartz.*;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.quartz.spi.OperableTrigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class QuartzServiceI{

    @Autowired
    private Scheduler scheduler;

    /**
     * 初始化定时任务
     * @param cron cron表达式
     * @param status 启动状态
     * @param jobName 任务名称
     * @param jobGroup 任务组
     * @param triName 触发器名称
     * @param triGroup 触发器组
     * @param task 任务类路径
     * @throws Exception
     */
    public void init(String cron,int status,
                     String jobName,String jobGroup,
                     String triName,String triGroup,
                     String task) throws Exception{
        //String cron = "";
        //判断表达式是否正确或是否有效
        if(isTimeOutExpression(cron)){

            //创建调度任务JobDetail
            JobDetail jd = JobBuilder.newJob(getClass(task).getClass())
                    .withIdentity(jobName,jobGroup)
                    .build();

            //创建表达式分析器
            CronScheduleBuilder cronBuilder =
                    CronScheduleBuilder.cronSchedule(cron);
            if(status == 0){
                cronBuilder.withMisfireHandlingInstructionIgnoreMisfires();//立即启动
            }else{
                cronBuilder.withMisfireHandlingInstructionDoNothing();//不立即执行
            }

            //创建触发器
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(triName,triGroup)
                    .withSchedule(cronBuilder)
                    .build();

            //判断该任务是否已经存在
            if(scheduler.checkExists(JobKey.jobKey(jobName,jobGroup))){
                scheduler.deleteJob(JobKey.jobKey(jobName,jobGroup));
            }

            //把任务与触发器结合
            scheduler.scheduleJob(jd,trigger);
            //启动
            scheduler.start();

        }
    }

    public BaseTask getClass(String classPath) throws Exception{
        Class<?> c = Class.forName(classPath);
        return (BaseTask)c.newInstance();
    }

    public boolean isTimeOutExpression(String cron){
        if(!CronExpression.isValidExpression(cron)){
            return false;
        }

        //声明触发器接口
        CronTriggerImpl impl = new CronTriggerImpl();
        try {
            impl.setCronExpression(cron);
        }catch (Exception e){
            System.out.println("定时任务cron已过期");
            return false;
        }

        Date date = impl.computeFirstFireTime(null);
        return date!=null && date.after(new Date());
    }

    @Transactional
    public boolean pauseJob(String jobName,String jobGroup){
        boolean b = false;
        try {
            scheduler.pauseJob(JobKey.jobKey(jobName,jobGroup));
            b = true;
        }catch (Exception e){
            System.out.println("任务暂停失败!");
            return false;
        }
        return b;
    }

    @Transactional
    public boolean resumeJob(String jobName,String jobGroup){
        boolean b = false;
        try {
            scheduler.resumeJob(JobKey.jobKey(jobName,jobGroup));
            b = true;
        }catch (Exception e){
            System.out.println("任务启动失败!");
            return false;
        }
        return b;
    }

    public List<String> recent5TriggerTime(String cron,int numTimes){
        List<String> list = new ArrayList<>();
        CronTrigger ct;
        try {
            ct = TriggerBuilder.newTrigger()
                    .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                    .build();
        }catch (Exception e){
            System.out.println("运行错误！");
            return list;
        }

        List<Date> dates = TriggerUtils.computeFireTimes((OperableTrigger)ct,null,numTimes);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(Date date:dates){
            list.add(sdf.format(date));
        }
        return list;
    }

}
